//
//  RCSQLDataBaseManager.m
//  RCDataBaseProject
//
//  Created by Roiy on 2017/7/31.
//  Copyright © 2017年 Roiy. All rights reserved.
//

#import "RCSQLDataBaseManager.h"

@implementation RCSQLDataBaseManager

+(instancetype)databaseWithPath:(NSString *)aPath
{
    return [[self alloc] initWithPath:aPath];
}

-(instancetype)initWithPath:(NSString *)path
{
    self = [super initWithPath:path];
    if (self) {

    }
    return self;
}

#pragma ---DataBase Operation Protocal--
-(BOOL)openDB
{
    if (_dataBase) {
        return YES;
    }
    int err = sqlite3_open([self sqlitePath], (sqlite3**)&_dataBase);
    if(err != SQLITE_OK) {
        NSLog(@"打开数据库失败： %d", err);
        return NO;
    }
    return YES;
}

-(BOOL)closeDB
{
    if (!_dataBase) {
        return YES;
    }
    int  rc;
    BOOL retry;
    BOOL triedFinalizingOpenStatements = NO;
    do {
        retry   = NO;
        rc      = sqlite3_close(_dataBase);
        if (SQLITE_BUSY == rc || SQLITE_LOCKED == rc) {
            if (!triedFinalizingOpenStatements) {
                triedFinalizingOpenStatements = YES;
                sqlite3_stmt *pStmt;
                while ((pStmt = sqlite3_next_stmt(_dataBase, nil)) !=0) {
                    NSLog(@"关闭statement");
                    sqlite3_finalize(pStmt);
                    retry = YES;
                }
            }
        }
        else if (SQLITE_OK != rc) {
            NSLog(@"关闭数据库状态码: %d",rc);
        }
    }
    while (retry);
    _dataBase = nil;
    return YES;
}

-(BOOL)executeHandle:(NSString *)sql, ...
{
    if (![self dataBaseExists])
    {
        return NO;
    }
    int handleResult        = 0x00;
    sqlite3_stmt *statement = 0x00;
    if (!statement) {
        handleResult = sqlite3_prepare_v2(_dataBase, [sql UTF8String], -1, &statement, 0);
        if (handleResult != SQLITE_OK)
        {
            NSLog(@"数据库executeHandle_prepare准备出错");
            sqlite3_finalize(statement);
            return NO;
        }
    }
    if (SQLITE_DONE != sqlite3_step(statement) )
    {
        NSLog(@"数据库executeHandle_step执行出错");
        sqlite3_finalize(statement);
        return NO;
    }
    int closeErrorCode = sqlite3_finalize(statement);
    if (closeErrorCode != SQLITE_OK) {
        NSLog(@"未知错误 (%d: %s)", closeErrorCode, sqlite3_errmsg(_dataBase));
    }
    return  YES;
}


-(id)executeQuery:(NSString *)sql, ...
{
    if (![self dataBaseExists])
    {
        return 0x00;
    }
    int handleResult         = 0x00;
    sqlite3_stmt *statement  = 0x00;
    RCResultSet *rcResultSet = 0x00;
    RCStatement *rcStatement = 0x00;
    if (!statement) {
        handleResult = sqlite3_prepare_v2(_dataBase, [sql UTF8String], -1, &statement, 0);
        if (handleResult != SQLITE_OK)
        {
            NSLog(@"数据库executeHandle_prepare准备出错");
            sqlite3_finalize(statement);
            return 0x00;
        }
    }
    if (!rcStatement) {
        rcStatement = [[RCStatement alloc]init];
        [rcStatement setStatement:statement];
    }
    rcResultSet = [RCResultSet resultSetWithStatement:rcStatement parentDB:self];
    [rcResultSet setQuery:sql];
    
    return rcResultSet;
}

#pragma mark ---Sqlite Tools--
- (const char*)sqlitePath {
    NSLog(@"数据库路径 ：%@",self.dataBasePath);
    return [self.dataBasePath fileSystemRepresentation];
}

- (BOOL)dataBaseExists {
    if (!_dataBase) {
        NSLog(@"数据库没有打开");
        return NO;
    }
    return YES;
}

#pragma mark ---Busy Handler Routines--
- (void)setMaxBusyRetryTimeInterval:(NSTimeInterval)timeout {

    self.maxBusyRetryTimeInterval = timeout;
    if (!_dataBase) {
        return;
    }
    if (timeout > 0) {
        sqlite3_busy_handler(_dataBase, &RCDataBaseBusyHandler, (__bridge void *)(self));
    }
    else {
        sqlite3_busy_handler(_dataBase, nil, nil);
    }
}

static int RCDataBaseBusyHandler(void *f, int count) {
    RCDataBaseManager *self = (__bridge RCDataBaseManager*)f;
    if (count == 0) {
        self->_startBusyRetryTime = [NSDate timeIntervalSinceReferenceDate];
        return 1;
    }

    NSTimeInterval delta = [NSDate timeIntervalSinceReferenceDate] - (self->_startBusyRetryTime);

    if (delta < [self maxBusyRetryTimeInterval]) {
        int requestedSleepInMillseconds = (int) arc4random_uniform(50) + 50;
        int actualSleepInMilliseconds = sqlite3_sleep(requestedSleepInMillseconds);
        if (actualSleepInMilliseconds != requestedSleepInMillseconds) {
        }
        return 1;
    }
    return 0;
}
@end
